/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package bs.facturacion.rn;

import bs.facturacion.dao.FacturacionDAO;
import bs.facturacion.modelo.CircuitoFacturacion;
import bs.facturacion.modelo.ItemAnulacionFacturacion;
import bs.facturacion.modelo.ItemAplicacionFacturacion;
import bs.facturacion.modelo.ItemMovimientoFacturacion;
import bs.facturacion.modelo.ItemProductoFacturacion;
import bs.facturacion.modelo.MovimientoFacturacion;
import bs.facturacion.vista.PendienteFacturacionDetalle;
import bs.facturacion.vista.PendienteFacturacionGrupo;
import bs.global.excepciones.ExcepcionGeneralSistema;
import bs.global.modelo.Comprobante;
import bs.global.modelo.Formulario;
import bs.global.modelo.Moneda;
import bs.global.rn.ComprobanteRN;
import bs.global.rn.FormularioRN;
import bs.global.rn.MonedaRN;
import bs.global.rn.SucursalRN;
import bs.global.util.JsfUtil;
import bs.stock.modelo.ComprobanteStock;
import bs.stock.modelo.MovimientoStock;
import bs.stock.rn.MovimientoStockRN;
import bs.tesoreria.modelo.ComprobanteTesoreria;
import bs.tesoreria.modelo.MovimientoTesoreria;
import bs.tesoreria.rn.MovimientoTesoreriaRN;
import bs.ventas.modelo.ComprobanteVenta;
import bs.ventas.modelo.MovimientoVenta;
import bs.ventas.rn.ListaPrecioRN;
import bs.ventas.rn.MovimientoVentaRN;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;


/**
 *
 * @author Claudio
 */
@Stateless
public class MovimientoFacturacionRN {

    @EJB private SucursalRN SucursalRN;
    @EJB private MonedaRN monedaRN;
    @EJB private FacturacionDAO facturacionDAO;
    @EJB private ComprobanteRN comprobanteDAO;
    @EJB private ListaPrecioRN listaPrecioRN;
    @EJB private FormularioRN formularioRN;
    @EJB private MovimientoVentaRN ventaRN;
    @EJB private MovimientoTesoreriaRN tesoreriaRN;
    @EJB private MovimientoStockRN stockRN;
    
//    @EJB private GR_MailFactory mailFactory;

    @TransactionAttribute(TransactionAttributeType.REQUIRED)   
    public synchronized void guardar(MovimientoFacturacion m) throws Exception {
        
        borrarItemsSinProductos(m);
        sincronizarCantidades(m);
        
        if(m.getComprobanteVenta()!=null){
            MovimientoVenta mv = ventaRN.generarComprobante(m);            
            m.setMovimientoVenta(mv);
        }
        
        if(m.getComprobanteTesoreria()!=null){
            MovimientoVenta mv = ventaRN.generarComprobante(m);            
            m.setMovimientoVenta(mv);
        }
        
        if(m.getComprobanteTesoreria()!=null){
            MovimientoTesoreria mt = tesoreriaRN.generarComprobante(m);            
            m.setMovimientoTesoreria(mt);
        }
        
        if(m.getComprobanteStock()!=null){
            MovimientoStock ms = stockRN.generarComprobante(m); 
            m.setMovimientoStock(ms);
        }
        
//        generarItemsDetalleVacio(m);
//        generarItemsSerie(m);
//        generarComprobanteStock(m);
//        generarItemsAnulacion(m);
//        borrarItemsSerie(m);
//        puedoGuardarMovimiento(m);

//        if (m.getCircuito().getActzst()=='S' && m.getMovimientoInventario()!=null){
//            inventarioRN.guardar(m.getMovimientoInventario());
//        }
        
        facturacionDAO.crear(m);        
        formularioRN.actualizarUltimoNumero(m.getFormulario());
        //incrementamos en 1 el numero de formulario
        m.getFormulario().setUltimoNumero(m.getFormulario().getUltimoNumero() + 1);        
        m.setPersistido(true);
        
        if(sincronizarIdAplicacion(m)){
            facturacionDAO.editar(m);
        }
        
    }

    public MovimientoFacturacion nuevoMovimiento(){
        return new MovimientoFacturacion();
    }

    public MovimientoFacturacion nuevoMovimiento(CircuitoFacturacion circuito) throws ExcepcionGeneralSistema{

        Comprobante comprobante = null;
        ComprobanteTesoreria comprobanteCJ = null;
        ComprobanteStock comprobanteST = null;
        ComprobanteVenta comprobanteVT = null;
        
        if (circuito.getActualizaFacturacion().equals("S")) {
            
            comprobante = circuito.getComprobanteFacturacion();

        }else if(circuito.getActualizaVenta().equals("S")){
            
            comprobante   = circuito.getComprobanteVenta();
            comprobanteVT = circuito.getComprobanteVenta();

            if (circuito.getActualizaTesoreria().equals("S")){
                
                comprobanteCJ = circuito.getComprobanteTesoreria();
            }

            if (circuito.getActualizaStock().equals("S")){
                
                comprobanteST = circuito.getComprobanteStock();
            }                                    

        }else if(circuito.getActualizaStock().equals("S")){                    

            comprobante = circuito.getComprobanteStock();
        }
        
        MovimientoFacturacion m = crearMovimiento(circuito, comprobante);
        
        if(comprobanteCJ!=null){
            m.setComprobanteTesoreria(comprobanteCJ);
        }
        
        if(comprobanteVT!=null){
            m.setComprobanteVenta(comprobanteVT);
        }
        
        if(comprobanteST!=null){
            m.setComprobanteStock(comprobanteST);
        }
        
        return m;
    }
    
    public MovimientoFacturacion nuevoMovimiento(CircuitoFacturacion circuito, PendienteFacturacionGrupo pendienteGrupo, List<PendienteFacturacionDetalle> itemsPendientes) throws ExcepcionGeneralSistema{

        MovimientoFacturacion m = nuevoMovimiento(circuito);
        
        m.setCliente(pendienteGrupo.getCliente());        
        m.setNrodoc(pendienteGrupo.getCliente().getNrodoc());
        m.setTipoDocumento(pendienteGrupo.getCliente().getTipoDocumento());
        m.setCondicionDeIva(pendienteGrupo.getCliente().getCondicionDeIva());
            
        m.setProvincia(pendienteGrupo.getCliente().getProvincia());
        m.setCodigoPostal(pendienteGrupo.getCodigoPostal());
        
        m.setBarrio(pendienteGrupo.getCliente().getBarrio());
        m.setDireccion(pendienteGrupo.getCliente().getDireccion());
        m.setNumero(pendienteGrupo.getCliente().getNumero());
        m.setDepartamentoPiso(pendienteGrupo.getCliente().getDepartamentoPiso());
        m.setDepartamentoNumero(pendienteGrupo.getCliente().getDepartamentoNumero());
                
        m.setCondicionDePago(pendienteGrupo.getCondicionDePago());        
        m.setListaDePrecio(pendienteGrupo.getListaDePrecio());        
        m.setMonedaListaPrecio(pendienteGrupo.getListaDePrecio().getMoneda());        
        m.setVendedor(pendienteGrupo.getVendedor());         
        
        generarItems(m, itemsPendientes);
        
        return m;
    }

    private MovimientoFacturacion crearMovimiento(CircuitoFacturacion circuito, Comprobante comprobante) throws ExcepcionGeneralSistema{

        if(comprobante==null) throw new ExcepcionGeneralSistema("El comprobante no puede ser nulo");
        
        MovimientoFacturacion m = new MovimientoFacturacion();
        Moneda moneda = monedaRN.getMoneda("USD");
        BigDecimal cotizacion  = monedaRN.getCotizacionDia("USD");
        
        m.setPersistido(false);
        m.setCircuito(circuito);
        m.setCongelaBonificacion(circuito.getCongelaBonificacion());
        m.setCongelaPrecio(circuito.getCongelaPrecio());
                
        m.setComprobante(comprobante);
        m.setFechaMovimiento(new Date());        
        m.setMonedaSecundaria(moneda);
        m.setCotizacion(cotizacion);
        
        asignarFormulario(m);
                
        if(comprobante.getDepositoIngreso()!=null){
            m.setDepositoIngreso(comprobante.getDepositoIngreso());            
        }

        if(comprobante.getDepositoEgreso()!=null){
            m.setDepositoEgreso(comprobante.getDepositoEgreso());            
        }
        
        if(circuito.getCircuitoComienzo().equals(circuito.getCircuitoAplicacion())){
            m.getItemsProducto().add((ItemProductoFacturacion) nuevoItemProducto(m));
        }

        return m;
    }

    public ItemProductoFacturacion nuevoItemProducto(MovimientoFacturacion m){
        
        ItemProductoFacturacion nItem = new ItemProductoFacturacion();        
        nItem.setIdItemAplicacion(nItem.getId());        
        nItem.setNroitm(m.getItemsProducto().size()+1);
        nItem.setCotizacion(m.getCotizacion());
        
        nItem.setMovimiento(m);
        nItem.setMovimientoAplicacion(m);
        nItem.setMovimientoInicial(m.getId());       
        nItem.setMovimientoOriginal(m.getId());

        return nItem;
    }

    public ItemAplicacionFacturacion nuevoItemAplicacion(MovimientoFacturacion m, PendienteFacturacionDetalle ip){

        ItemAplicacionFacturacion nItem = new ItemAplicacionFacturacion();
        nItem.setIdItemAplicacion(ip.getIdItemAplicacion());        
        nItem.setNroitm(m.getItemsAplicacion().size()+1);    
        nItem.setCotizacion(m.getCotizacion());
        
        nItem.setMovimiento(m);        
        nItem.setMovimientoAplicacion(ip.getMovimientoAplicacion());
        nItem.setMovimientoInicial(ip.getIdMovimientoAplicacion());
        nItem.setMovimientoOriginal(ip.getIdMovimientoAplicacion());
                

        return nItem;
    }

    public ItemAnulacionFacturacion nuevoItemAnulacion(MovimientoFacturacion m, ItemMovimientoFacturacion ip){

        ItemAnulacionFacturacion nItem = new ItemAnulacionFacturacion();
        nItem.setNroitm(m.getItemsAnulacion().size()+1);
        nItem.setCotizacion(m.getCotizacion());
        
        //Buscamos el items aplicación del items que estamos aplicando para anular el item aplicado
//        ItemMovimientoFacturacionPK idPK = new ItemMovimientoFacturacionPK(ip.getModapl(), ip.getCodapl(), ip.getNroapl(), ip.getItmapl(), "2", ip.getModapl(), ip.getCodapl(), ip.getNroapl(), ip.getItmapl(), "2");
        
        ItemMovimientoFacturacion iAnulado = getItemAplicacion(1);        

        nItem.setMovimiento(m);
        nItem.setMovimientoInicial(m.getId());
        nItem.setMovimientoOriginal(m.getId());

        return nItem;
    }

    public ItemAplicacionFacturacion getItemAplicacion(Integer id) {

        return facturacionDAO.getItemAplicacion(id);
    }

    public boolean eliminarItemProducto(MovimientoFacturacion mov,  ItemProductoFacturacion nItem){

        boolean fItemBorrado = false;
        int i = 0;
        int indiceItemProducto = -1;
        int indiceItemAplicacion = -1;
        int indiceItemAnulacion = -1;

        for(ItemProductoFacturacion ip: mov.getItemsProducto()){

            if(ip.getProducto()!=null){

                if(ip.getProducto().equals(nItem.getProducto())){
                    indiceItemProducto = i;
                }
            }
            i++;
        }

        i = 0;

        //Buscamos indice de item aplicación
        if(mov.getItemsAplicacion()!=null){
            for(ItemAplicacionFacturacion a: mov.getItemsAplicacion()){

                if(a.getProducto().equals(nItem.getProducto())){
                    indiceItemAplicacion = i;
                }
                i++;
            }
        }

        //Buscamos indice de item anulación
        if(mov.getItemsAnulacion()!=null){
            for(ItemAnulacionFacturacion a: mov.getItemsAnulacion()){

                if(a.getProducto().equals(nItem.getProducto())){
                    indiceItemAnulacion = i;
                }
                i++;
            }
        }

        //Borramos los items productos
        if(indiceItemProducto>=0){
            ItemProductoFacturacion remove = mov.getItemsProducto().remove(indiceItemProducto);
            if(remove!=null){
                fItemBorrado = true;
            }
        }

        //Borramos los items aplicación si existen
        if(indiceItemAplicacion>=0){
            ItemAplicacionFacturacion remove = mov.getItemsAplicacion().remove(indiceItemAplicacion);
            if(remove!=null){
                fItemBorrado = true;
            }
        }

        //Borramos los items aplicación si existen
        if(indiceItemAnulacion>=0){
            ItemAnulacionFacturacion remove = mov.getItemsAnulacion().remove(indiceItemAnulacion);
            if(remove!=null){
                fItemBorrado = true;
            }
        }
        
        return fItemBorrado;
    }

    public void asignarFormulario(MovimientoFacturacion m) throws ExcepcionGeneralSistema {
        
        if(m.getCliente()==null){
            return;
        }
        
        Formulario formulario;        
        //Buscamos el formulario correspondiente
        if(m.getCircuito().getActualizaFacturacion().equals("S") || m.getCondicionDeIva()==null){                     
            formulario = formularioRN.getFormulario(m.getComprobante(),"X");                                 
        }else{            
            formulario = formularioRN.getFormulario(m.getComprobante(), m.getCondicionDeIva().getCodigo());
        }        
        
        m.setNumeroFormulario(formulario.getUltimoNumero());
        m.setFormulario(formulario);
        m.setSucursal(formulario.getSucursal());
        
    }

    private void borrarItemsSinProductos(MovimientoFacturacion m) {
        
        int i = 0;
        int indiceBorrar = -1;
        
        for(ItemMovimientoFacturacion im:m.getItemsProducto()){
            if(im.getProducto()==null && !im.isTodoOk()){
                indiceBorrar = i;
            }
        }
        
        //Borramos los items productos
        if(indiceBorrar>=0){
            ItemProductoFacturacion remove = m.getItemsProducto().remove(indiceBorrar);            
        }
        
    }

    public void seleccionarTodo(List<PendienteFacturacionDetalle> itemsPendiente, boolean seleccionarTodo) {
        
        if(itemsPendiente==null) return;

        for(PendienteFacturacionDetalle i: itemsPendiente){
            i.setSeleccionado(seleccionarTodo);
        }
    }

    public List<PendienteFacturacionGrupo> getPendienteGrupo(Map<String, String> filtroGrupo) {
        return facturacionDAO.getPendienteGrupo(filtroGrupo);
    }

    public List<PendienteFacturacionDetalle> getPendienteDetalle(Map<String, String> filtroDetalle) {        
        return facturacionDAO.getPendienteDetalle(filtroDetalle);
    }
    
    public void generarItems(MovimientoFacturacion m, List<PendienteFacturacionDetalle> itemsPendiente) throws ExcepcionGeneralSistema {

        if(itemsPendiente.isEmpty()){
            return;
        }
        
        int cantSel = 0;
        for (PendienteFacturacionDetalle i : itemsPendiente){

            if (i.isSeleccionado()) {

                cantSel++;
                ItemProductoFacturacion nItem = (ItemProductoFacturacion) nuevoItemProducto(m);

                nItem.setProducto(i.getProducto());
                nItem.setProductoOriginal(i.getProducto());
                nItem.setConcepto(i.getProducto().getConceptoVenta());
                nItem.setUnidadMedida(i.getProducto().getUnidadDeMedida());                
                nItem.setCantidad(i.getCantidad());                
                nItem.setCantidadOriginal(i.getCantidad());
                nItem.setPrecio(i.getPrecio());
                nItem.setTodoOk(true);

                //Agregamos el item a la lista
                m.getItemsProducto().add(nItem);
                
                //Verificamos si el circuito aplica a items pendietnes
                if(m.getCircuito().getNoCancelaPendiente().equals("N")){

                    //Genera los items aplicación
                    ItemAplicacionFacturacion iApl = nuevoItemAplicacion(m, i);

                    iApl.setProducto(i.getProducto());
                    iApl.setProductoOriginal(i.getProducto());
                    iApl.setConcepto(i.getProducto().getConceptoVenta());
                    iApl.setUnidadMedida(i.getProducto().getUnidadDeMedida());
                    iApl.setCantidad(i.getCantidad().negate());
                    iApl.setCantidadOriginal(i.getCantidad());
                    iApl.setPrecio(i.getPrecio());
                    
                    nItem.setTodoOk(true);
                    
                    m.getItemsAplicacion().add(iApl);                            
                }
            }
        }
        if (cantSel == 0) {
            throw  new ExcepcionGeneralSistema("No ha seleccionado ningún producto");
        }
    }
 
    public void calcularImportesLinea(ItemProductoFacturacion item){
                
        if(item.getCantidad()==null){
            item.setCantidad(BigDecimal.ZERO);
        }
        
        if(item.getPrecio()==null){
            item.setPrecio(BigDecimal.ZERO);
        }
        
        if(item.getPorcentajeBonificacion1()==null){
            item.setPorcentajeBonificacion1(BigDecimal.ZERO);
        }
        
        if(item.getPorcentajeBonificacion2()==null){
            item.setPorcentajeBonificacion2(BigDecimal.ZERO);
        }
        
        if(item.getPorcentajeBonificacion3()==null){
            item.setPorcentajeBonificacion3(BigDecimal.ZERO);
        }
        
        if(item.getPorcentajeBonificacion4()==null){
            item.setPorcentajeBonificacion4(BigDecimal.ZERO);
        }
        
        if(item.getPorcentajeBonificacion5()==null){
            item.setPorcentajeBonificacion5(BigDecimal.ZERO);
        }
        
        if(item.getPorcentajeBonificacion6()==null){
            item.setPorcentajeBonificacion6(BigDecimal.ZERO);
        }
        
        BigDecimal porcentTotalBonif = item.getPorcentajeBonificacion1().add(item.getPorcentajeBonificacion2()).add(item.getPorcentajeBonificacion3()).add(item.getPorcentajeBonificacion4()).add(item.getPorcentajeBonificacion5()).add(item.getPorcentajeBonificacion6());        
        item.setPorcentaTotalBonificacion(porcentTotalBonif);
        
        BigDecimal bonif = item.getPrecio().multiply(item.getPorcentaTotalBonificacion().divide(new BigDecimal(100)));
        BigDecimal totalLinea = item.getCantidad().multiply(item.getPrecio().add(bonif));                    
        item.setTotalLinea(totalLinea);            
    }
    
    public void sincronizarCantidades(MovimientoFacturacion m){

        for(ItemProductoFacturacion i: m.getItemsProducto()){

            if(i.getCantidad()==null || i.getCantidad().compareTo(BigDecimal.ZERO)<=0){
                JsfUtil.addErrorMessage("Ingrese un valor de cantidad válido. Mayor a 0");
                return;
            }

            if(m.getItemsAplicacion()!=null){

                for(ItemAplicacionFacturacion a: m.getItemsAplicacion()){

                    if(i.getProducto().equals(a.getProducto()) && i.getNroitm()==a.getNroitm()){

                        //Items aplicación van con valores negativos
                        a.setCantidad(i.getCantidad().negate());                        
                    }
                }
            }
        }
    }

    private boolean sincronizarIdAplicacion(MovimientoFacturacion m){
        
        boolean sincronizar = false;
        
        for(ItemProductoFacturacion ip: m.getItemsProducto()){
            
            if(ip.getIdItemAplicacion()==null){
                ip.setIdItemAplicacion(ip.getId());
                sincronizar = true;
            }            
        }
        
        return sincronizar;
    }
}

